---@class TBS.EffectMgr
local EffectMgr = TBS.CreateSingleton("EffectMgr")
local this = EffectMgr
function EffectMgr.OnCreate()
    ---@type TBS.EffectBase[]
    this.effectList = {}
    ---@type TBS.EffectBase[]
    this.tempList = {}
    this.staticUniqueId = 0
    ---@type TBS.EffectBase[]
    this.removedList = {}
    TBS.Battle.RegisterUpdateCallback(this.Update)
end
function EffectMgr.OnDestroy()
    if this.effectList then
        for k,v in pairs(this.effectList) do
            v:OnDestroy()
        end
    end
    this.tempList = nil
    this.removedList = nil
end
function EffectMgr.GetUniqueId()
    this.staticUniqueId = this.staticUniqueId + 1
    return this.staticUniqueId
end
function EffectMgr.GetPos(originX,originY,offsetX,offsetY)
    local x = originX + offsetX
    local y = originY + offsetY
    return x,y
end
function EffectMgr.CreateEffect2(casterId,resName,action,posX,posY)
    local effect = TBS.PoolMgr.GetEffectFromPool(this.GetUniqueId(),TBS.Config.EffectType.effect)
    effect:OnCreate()
    effect.casterId = casterId
    effect.animName = action
    effect.resName = resName
    effect.pos:Set(posX,posY)
    effect.during = -1
    this.AddEffect(effect)
    effect:Play()
    return effect
end
---@param effectData TBS.EffectNode
---@return TBS.EffectBase
function EffectMgr.CreateEffect(casterId, targetId, skillId, effectData)
    if effectData == nil or string.IsNilOrEmpty(effectData.resName) then
        return
    end
    ---@type TBS.EffectBase
    local effect
    if effectData.isBullet then
        effect = TBS.PoolMgr.GetEffectFromPool(this.GetUniqueId(),TBS.Config.EffectType.bullet)
    elseif effectData.isUltimateEffect then
        effect = TBS.PoolMgr.GetEffectFromPool(this.GetUniqueId(),TBS.Config.EffectType.ultimate)
    elseif effectData.isProduceByTeamAllHeroAndFollow then
        effect = TBS.PoolMgr.GetEffectFromPool(this.GetUniqueId(),TBS.Config.EffectType.followUI)
    else
        effect = TBS.PoolMgr.GetEffectFromPool(this.GetUniqueId(),TBS.Config.EffectType.effect)
    end
    effect:OnCreate()
    effect.casterId = casterId or 0
    effect.targetId = targetId or 0
    effect.animName = effectData.resAction
    effect.resName = effectData.resName
    effect.skillId = skillId or 0
    effect.delayDieTime = effectData.delayDestroyTime
    effect.scale = effectData.scale
    effect:SetAnimEvent(effectData.animationEvent)
    local EffectPosType = TBS.Config.EffectPosType
    if effectData.PosType == EffectPosType.caster then  --施法者
        local a = TBS.ActorMgr.GetActor(casterId)
        local p = a:GetPos()
        effect.pos:Set(p.x+effectData.offX,p.y+effectData.offY)
    elseif effectData.PosType == EffectPosType.target then  --目标
        local a = TBS.ActorMgr.GetActor(targetId)
        local p = a:GetPos()
        effect.pos:Set(p.x+effectData.offX,p.y+effectData.offY)
    elseif effectData.PosType == EffectPosType.fixPos  then
        effect.pos:Set(effectData.offX,effectData.offY)
    elseif effectData.PosType == EffectPosType.AllGroupCenter then
        local x,y = TBS.Battle.GetAllLeaderCenterPosition()
        effect.pos:Set(x + effectData.offX,y + effectData.offY)
    elseif effectData.PosType == EffectPosType.curGroupCenter then
        local a = TBS.ActorMgr.GetActor(casterId)
        local x,y = TBS.Battle.GetLeaderPosition(a:GetGroupId())
        effect.pos:Set(x + effectData.offX,y + effectData.offY)
    elseif effectData.PosType == EffectPosType.Boss then
        local b = TBS.ActorMgr.GetBoss()
        local p = b:GetPos()
        effect.pos:Set( p.x+ effectData.offX,p.y + effectData.offY)
    elseif effectData.PosType == EffectPosType.screenCenter then
        local x,y = TBS.Battle.ScreenToScenePoint(Screen.width/2,Screen.height/2)
        effect.pos:Set( x,y)
    else
        logError(effectData.skill.skillId.." skill未指定f_Target: "..effectData.PosType)
        effect.pos:Set(0,0)
    end
    effect:SetEffectLoadDoneCallback(effectData.effectLoadDoneCallback,effectData.effectLoadDoneCallbackTB)

    local leftRandom = 0
    if effectData.hasRandomBorn then
        math.randomseed(TBS.Battle.GetUniqueId()*100)
        leftRandom = math.random()
        local r1 = this.Lerp(effectData.randomBornMinX,effectData.randomBornMaxX,leftRandom)
        local t = math.random()
        local r2 = this.Lerp(effectData.randomBornMinY,effectData.randomBornMaxY,t)
        effect.pos:Set(effect.pos.x+r1,effect.pos.y+r2)
    end
    if effectData.hasRandomRotate then
        local r1 = this.Lerp(effectData.randomRotateMin,effectData.randomRotateMax,leftRandom)
        effect:SetRotate(r1)
    end
    if effectData.isUltimateEffect then
        effect:SetDrawingName(effectData.drawingName)
    end
    if effectData.isProduceByTeamAllHeroAndFollow then
        local a = TBS.ActorMgr.GetActor(targetId)
        effect:SetFollow(a:GetGroupId(),a:GetGroupIndex())
    end
    effect.during = effectData.resDuring or -1
    if effectData:HasRandomRes() then
        local index = math.random(1,#effectData.randomRes)
        effect.resName = effectData.randomRes[index]
    end
    if effectData.hasRandomTargetPos then
        local a = TBS.ActorMgr.GetActor(targetId)
        local caster = TBS.ActorMgr.GetActor(casterId)
        local groupIndex = caster:GetGroupIndex()
        local groupId = caster:GetGroupId()
        ---@type TBS.Bullet
        local bullet = effect
        if a then
            local x = 0
            local random = math.random()
            random = this.Lerp(effectData.randomTargetMinX,effectData.randomTargetMaxX,random)
            x = a:GetPos().x + random
            random = math.random()
            local y = a:GetPos().y + this.Lerp(effectData.randomTargetMinY,effectData.randomTargetMaxY,random)
            bullet:SetFixTargetPos(x,y)
        end
        --曲线
        local randomX = 0.5 * (groupIndex-4)
        randomX = math.max(-2,randomX)
        randomX = math.min(2,randomX)
        --local randomX = 50 * (groupIndex-4)
        --randomX = math.max(-200,randomX)
        --randomX = math.min(200,randomX)
        local ctrlX = effect.pos.x + randomX
        local ctrlY = effect.pos.y + 1*(groupId)
        bullet:SetPathType(TBS.Config.BulletPathType.curve)
        bullet:SetCtrlPoint(ctrlX,ctrlY)
    end
    this.AddEffect(effect)
    effect:Play()
    return effect
end
function EffectMgr.Lerp(a,b,t)
    return t*(b-a) + a
end
---@private
---@param effect TBS.EffectBase
function EffectMgr.EffectToPool(effect)
    effect:OnDestroy()
    TBS.PoolMgr.ReturnEffectToPool(effect)
end
function EffectMgr.DestroyEffect(effect)
    if not effect then return end
    this.effectList[effect.id] = nil
    this.EffectToPool(effect)
end
function EffectMgr.DestroyEffectByCaster(casterId)
    for k,v in pairs(this.effectList) do
        if v.casterId == casterId then
           v:Die()
        end
    end
end
function EffectMgr.DestroyEffectBySkill(skillId)
    for k,v in pairs(this.effectList) do
        if v.skillId == skillId then
            v:Die()
        end
    end
end
---@param effect TBS.EffectBase
function EffectMgr.AddEffect(effect)
    this.effectList[effect.id] = effect
end
function EffectMgr.Update(dt)
    table.clear(this.removedList)
    table.clear(this.tempList)
    for k,v in pairs(this.effectList) do
        this.tempList[k] = v
    end
    for k,v in pairs(this.tempList) do
        v:Update(dt)
        if v:IsDie() then
            table.insert(this.removedList,v)
        end
    end
    --
    for k,v in pairs(this.removedList) do
        this.DestroyEffect(v)
    end
end